/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "timer_mgr.h"
#include "iotc_oh_sle.h"
#include "control_value.h"
#include "iot_connect_log.h"
#include "sle_bridge_errors.h"
#include "iotc_json.h"

namespace OHOS {
namespace iotConnect {
int32_t ControlValue::DevInfoGetCharState(const IotcCharState inData, std::string *data, uint32_t *len) const
{
#if IOTC_CONF_DEV_TYPE == 2
    int32_t res = SLE_BRIDGE_FAILED;

    cJSON *json = cJSON_ParseWithLength(inData.data, inData.len);
    if (nullptr == json) {
        HILOGE("create json error");
        return -1;
    }

    if (cJSON_AddStringToObject(json, "allSvcFlag", "0") == NULL) {
        cJSON_Delete(json);
        HILOGE("add brand error");
        return SLE_BRIDGE_ERR_ADD_JSON_DATA;
    }

    std::string tempData = cJSON_PrintUnformatted(json);
    res = IotcOhSleSendCustomSecData(inData.devId, (uint8_t *)tempData.c_str(), tempData.length());
    if (res != SLE_BRIDGE_SUCCESS) {
        HILOGE("IotcOhSleSendCustomSecData error, res: %{public}d", res);
        return SLE_BRIDGE_FAILED;
    }

    HILOGI("send message success, msgId: %{public}s", inData.msgId);
    TimerMgr::GetInstance()->SubThingModelWaitReply(inData);
#endif
    return SLE_BRIDGE_SUCCESS;
}

int32_t ControlValue::ConfigurationManagementGetCharState(const IotcCharState inData, std::string *data, uint32_t *len)
{
    return SLE_BRIDGE_SUCCESS;
}

int32_t ControlValue::ConfigurationManagementPutCharState(const IotcCharState inData, const char *data, uint32_t len)
{
    return SLE_BRIDGE_SUCCESS;
}

int32_t ControlValue::InternalHandler(const IotcCharState inData, std::string& out, ThingModelPutOrGet flag)
{
    auto iter = mapThingModelSvcControl.find(std::string(inData.svcId));
    if (mapThingModelSvcControl.end() == iter) {
        HILOGE("not find svrId, svrId:%{public}s", inData.svcId);
        return SLE_BRIDGE_ERR_INVALID_PARAM;
    }

    SvcType type = static_cast<SvcType>(iter->second);
    switch (type) {
        case SvcType::DEV_INFO: {
            if (flag == ThingModelPutOrGet::GET) {
                std::string tempOut;
                uint32_t tempLen = 0;
                this->DevInfoGetCharState(inData, &tempOut, &tempLen);
                if (!tempOut.empty()) {
                    out = tempOut;
                }
            }
            break;
        }
        default:
            HILOGE("not find svrId, svrId:%{public}s", inData.svcId);
            break;
    }
    return SLE_BRIDGE_SUCCESS;
}

int32_t ControlValue::GetAllInfoHandler(const std::string &devId, IotcCharState *state)
{
#if IOTC_CONF_DEV_TYPE == 2
    int32_t ret = SLE_BRIDGE_FAILED;

    cJSON *json = cJSON_CreateObject();
    if (json == NULL) {
        HILOGE("create obj error");
        return SLE_BRIDGE_ERR_CREATE_JSON;
    }

    if (cJSON_AddStringToObject(json, "allSvcFlag", "1") == NULL) {
        cJSON_Delete(json);
        HILOGE("add brand error");
        return SLE_BRIDGE_ERR_ADD_JSON_DATA;
    }

    IotcCharState iotcState;
    iotcState.devId = devId.c_str();
    iotcState.data = cJSON_PrintUnformatted(json);
    iotcState.len = strlen(iotcState.data);

    ret = IotcOhSleSendCustomSecData(devId.c_str(), (uint8_t *)iotcState.data, iotcState.len);
    if (ret != SLE_BRIDGE_SUCCESS) {
        HILOGE("IotcOhSleSendCustomSecData error, ret: %{public}d", ret);
        cJSON_Delete(json);
        return SLE_BRIDGE_FAILED;
    }

    HILOGI("success send message to sub dev, msgId");
    TimerMgr::GetInstance()->SubThingModelWaitReply(std::move(iotcState));
    cJSON_Delete(json);
#endif
    return SLE_BRIDGE_SUCCESS;
}

static int32_t buildGasControlJson(IotcJson **root, bool on)
{
    *root = IotcJsonCreate();
    if (*root == nullptr)
        return SLE_BRIDGE_ERR_CREATE_JSON;

    IotcJson *data = IotcJsonCreate();
    if (!data || IotcJsonAddNum2Obj(data, "switch", on ? 1 : 0)) {
        IotcJsonDelete(data);
        return SLE_BRIDGE_ERR_CREATE_JSON;
    }

    IotcJson *vendorItem = IotcJsonCreate();
    if (!vendorItem || IotcJsonAddStr2Obj(vendorItem, "sid", "serviceList") ||
        IotcJsonAddStr2Obj(vendorItem, "st", "serviceList") || IotcJsonAddItem2Obj(vendorItem, "data", data)) {
        IotcJsonDelete(vendorItem);
        return SLE_BRIDGE_ERR_ADD_JSON_DATA;
    }

    IotcJson *vendorArray = IotcJsonCreateArray();
    if (!vendorArray || IotcJsonAddItem2Array(vendorArray, vendorItem) ||
        IotcJsonAddItem2Obj(*root, "vendor", vendorArray) || IotcJsonAddNum2Obj(*root, "seq", 0)) {
        IotcJsonDelete(vendorArray);
        return SLE_BRIDGE_ERR_ADD_JSON_DATA;
    }
    return SLE_BRIDGE_SUCCESS;
}
int32_t ControlValue::switchGasValue(const std::string &devId, bool on)
{
    IotcJson *root = nullptr;
    int32_t ret = buildGasControlJson(&root, on);
    if (ret != SLE_BRIDGE_SUCCESS)
        return ret;

    IotcCharState iotcState;
    const char *id = "serviceList";
    iotcState.svcId = strdup(id);
#if IOTC_CONF_DEV_TYPE == 2
    iotcState.devId = devId.c_str();
#endif
    iotcState.data = IotcJsonPrint(root);
    iotcState.len = strlen(iotcState.data);

    ret = IotcOhSleSendCustomSecData(devId.c_str(), (uint8_t *)iotcState.data, iotcState.len);
    if (ret != SLE_BRIDGE_SUCCESS) {
        HILOGE("IotcOhSleSendCustomSecData error, ret: %{public}d", ret);
        IotcJsonDelete(root);
        return SLE_BRIDGE_FAILED;
    }

    HILOGI("success send message to sub dev");
    TimerMgr::GetInstance()->SubThingModelWaitReply(std::move(iotcState));
    IotcJsonDelete(root);

    return SLE_BRIDGE_SUCCESS;
}
} // namespace iotConnect
} // namespace OHOS
